local GetPlayerController = cj.GetPlayerController
local MAP_CONTROL_USER = cj.MAP_CONTROL_USER
local GetPlayerSlotState = cj.GetPlayerSlotState
local PLAYER_SLOT_STATE_PLAYING = cj.PLAYER_SLOT_STATE_PLAYING
local SetPlayerAlliance = cj.SetPlayerAlliance

xconst.player.PLAYER_SLOT_STATE_PLAYING = PLAYER_SLOT_STATE_PLAYING --正在游戏中
xconst.player.MAP_CONTROL_USER = MAP_CONTROL_USER --用户


local allianceType = {  }
---@class mPlayer [1-16]为玩家对象
---@type player[]
player = {
    type = 'module',
    module = 'player',
    count = 0, --玩家数量
    _h2o = {},
}
player.__index = player
---@class cPlayer
---@field private handle userdata 魔兽handle
---@field private ally table<player,bool>
local cPlayer = {
    type = 'class',
    class = 'player',

}
cPlayer.__index = cPlayer

player.cPlayer = cPlayer

---@private 用将id转化为玩家对象 会返回已经创建过的player
---@param id int 按魔兽为准
---@return player
function player:new( id )
    if self[id+1] then return self[id+1] end
    local p = cj.Player(id)
    local hid = cj.GetHandleId(p)
    local name = cj.GetPlayerName(p)
    ---@class player : cPlayer
    ---@field id int 玩家id 1-16
    local t = {
        id = id + 1,
        handle = p,
        orig_name = name,
        name = name,
        hid = hid,

        ally = {}, --player,bool 友军
    }
    self._h2o[ hid ] = t
    setmetatable( t, cPlayer )

    t:init()

    return t
end

---@private
function cPlayer:init()
    ---@type event[] 已注册的玩家事件
    self.events = {}
    --事件模块还未初始化
    --player:update( '玩家-初始化', { player = self } )
end

---@private
---@return player
function player:h2o( h )
    local hid = cj.GetHandleId( h )
    if hid == 0 then return end
    if player._h2o[ hid ] then
        return player._h2o[ hid ]
    end
    local obj = self:new( cj.GetPlayerId(h) )
    return obj
end



function cPlayer:is_player()
	return GetPlayerController(self.handle) == MAP_CONTROL_USER and GetPlayerSlotState(self.handle) == PLAYER_SLOT_STATE_PLAYING
end

--是否是裁判
function cPlayer:isObserver()
	return cj.IsPlayerObserver(self.handle)
end

--是否是本地玩家
function cPlayer:is_self()
	return self == player.self
end

--设置玩家名字
function cPlayer:setName(name)
	cj.SetPlayerName(self.handle, name)
    self.name = name
end

--禁止框选
function cPlayer:disableDragSelect()
	if self == player.self then
		cj.EnableDragSelect(false, false)
	end
end

--允许框选
function cPlayer:enableDragSelect()
	if self == player.self then
		cj.EnableDragSelect(true, true)
	end
end

--发送屏幕消息
---@param text string  消息内容
---@param time number   [持续时间] 默认60
function cPlayer:msg(text, time)
	cj.DisplayTimedTextToPlayer(self.handle, 0, 0, time or 60, text)
end

--清空屏幕显示
function cPlayer:clearMsg()
	if self == player.self then
		cj.ClearTextMessages()
	end
end

--强制按键
---@param key string 按下的键('ESC'表示按下ESC键)
function cPlayer:pressKey(key)
	if self ~= player.self then
		return
	end

	key = key:upper()

	if key == 'ESC' then
		cj.ForceUICancel()
	else
		cj.ForceUIKey(key)
	end
end

--增加玩家 黄金
function cPlayer:addGold(gold)
	cj.SetPlayerState(
        self.handle,
        cj.PLAYER_STATE_RESOURCE_GOLD,
        cj.GetPlayerState(self.handle,cj.PLAYER_STATE_RESOURCE_GOLD) + gold
    )
end

--增加玩家 木材
function cPlayer:addLumber(lumber)
	cj.SetPlayerState(
        self.handle,
        cj.PLAYER_STATE_RESOURCE_LUMBER,
        cj.GetPlayerState(self.handle,cj.PLAYER_STATE_RESOURCE_LUMBER) + lumber
    )
end

--增加玩家 已使用食物
function cPlayer:addUsedfood( food )
	cj.SetPlayerState(
        self.handle,
        cj.PLAYER_STATE_RESOURCE_FOOD_USED,
        cj.GetPlayerState(self.handle,cj.PLAYER_STATE_RESOURCE_FOOD_USED) + food
    )
end

--获得玩家 木材
function cPlayer:getLumber()
	return cj.GetPlayerState(
        self.handle,
        cj.PLAYER_STATE_RESOURCE_LUMBER
    )
end

--获得玩家 食物（已使用）
function cPlayer:getUsedFood()
	return cj.GetPlayerState(
        self.handle,
        cj.PLAYER_STATE_RESOURCE_FOOD_USED
    )
end

--获得玩家 黄金
function cPlayer:getGold()
	return cj.GetPlayerState(
        self.handle,
        cj.PLAYER_STATE_RESOURCE_GOLD
    )
end

--启用技能
---@param ability_id string 字符串id
function cPlayer:enable_ability(ability_id)
    if ability_id then
        cj.SetPlayerAbilityAvailable(self.handle, base.iid(ability_id), true)
    end
end

--禁用技能
---@param ability_id string 字符串id
function cPlayer:disable_ability(ability_id)
    if ability_id then
        cj.SetPlayerAbilityAvailable(self.handle, base.iid(ability_id), false)
    end
end
local color_word = {}

--获得玩家颜色  |c开头的颜色代码
function cPlayer:getColorWord()
	return color_word[self.id]
end

--- 对目标玩家设置联盟选项  allitype 默认结盟
---@param targetPlayer player 目标玩家
---@param allitype string 结盟|共享视野|共享单位|共享完全控制权|共享经验|盟友魔法锁定|救援请求|救援回应
---@param enable bool 是否启用
function cPlayer:setAlliance( targetPlayer, allitype, enable )
    local b = false
    if enable then b = true end
    local type = allitype
    if not allianceType[ type ] then
        type = '结盟' --设置个默认项
    end
    SetPlayerAlliance( self.handle, targetPlayer.handle, allianceType, b )

    if type == '结盟' then
        targetPlayer.ally[ self ] = b
    end
end

--- 判断是否是目标玩家的盟友（在目标玩家看来）
---@param targetPlayer player
function cPlayer:isAlly( targetPlayer )
    return targetPlayer.ally[ self ]
end

--- 判断是否是目标玩家的盟友（双向判断）
---@param targetPlayer player
function cPlayer:isAllyTwoWay( targetPlayer )
    return targetPlayer.ally[ self ] and self.ally[ targetPlayer ]
end


allianceType[ '结盟' ] = cj.ALLIANCE_PASSIVE
allianceType['共享视野'] = cj.ALLIANCE_SHARED_VISION
allianceType['共享单位'] = cj.ALLIANCE_SHARED_CONTROL
allianceType['共享完全控制权'] = cj.ALLIANCE_SHARED_ADVANCED_CONTROL
allianceType['共享经验'] = cj.ALLIANCE_SHARED_XP
allianceType['盟友魔法锁定'] = cj.ALLIANCE_SHARED_SPELLS
allianceType['救援请求'] = cj.ALLIANCE_HELP_REQUEST
allianceType['救援回应'] = cj.ALLIANCE_HELP_RESPONSE

----------init

for i=1,16 do
    ---@type player[]
    player[ i ] = player:new( i-1 )
    if player[i]:is_player() then
        player.count = player.count + 1
    end
end
local IsPlayerAlly = cj.IsPlayerAlly
--- 初始化联盟判断依据
for i=1,16 do
    local source = player[i]
    for j=1,16 do
        local target = player[j]
        local ally = IsPlayerAlly( source.handle, target.handle )
        target.ally[ source ] = ally
    end
end
---@type player 本地玩家
player.self = player:new( cj.GetPlayerId( cj.GetLocalPlayer() ) )

color_word [1] = "|cFFFF0303"
color_word [2] = "|cFF0042FF"
color_word [3] = "|cFF1CE6B9"
color_word [4] = "|cFF540081"
color_word [5] = "|cFFFFFC01"
color_word [6] = "|cFFFE8A0E"
color_word [7] = "|cFF20C000"
color_word [8] = "|cFFE55BB0"
color_word [9] = "|cFF959697"
color_word[10] = "|cFF7EBFF1"
--color_word[11] = "|cFF106246"
-- color_word[12] = "|cFF4E2A04"
color_word[11] = "|cFFFFFC01"
color_word[12] = "|cFF0042FF"
color_word[13] = "|cFF282828"
color_word[14] = "|cFF282828"
color_word[15] = "|cFF282828"
color_word[16] = "|cFF282828"
